Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Check lstat before calling realpath #41288

Closed
wants to merge 1 commit into from

Conversation

amcasey
Copy link
Member

@amcasey amcasey commented Oct 27, 2020

The only thing we're using realpath for is to resolve symlinks and most files and directories are not symlinks. This change skips the expensive realpath call for non-symlinks.

Q: Shouldn't we add lstat to the System interface?
A: Strictly speaking, we probably should, but the behavior of our realpath isn't actually documented anywhere, so we're not really locked in, and we want this at all call sites, so we'd have to add a layer of abstraction anyway.

Q: What if it is a symlink? Won't it be slower?
A: I believe (based on previous forays in the node/libuv codebase), but haven't proven, that libuv (and probably the OS) caches lstat results so the "real" lstat call in realpath should be basically free, for a negligible net increase.

Q: How was this validated?
A: This was inspired by my profiling of project loading (specifically createProgram) in one of the Office codebases. In that code, the project loading time is 6% faster on Windows and 20% faster on Linux (we call realpath as part of many of our existence checks and I conjecture that the lack of recursive file watching on Linux requires more of these). I also confirmed that xstate-analytics, which is part of a lerna monorepo and pulls in dependencies via symlinks in node_modules, was about 5% faster on Windows.

The only thing we're using realpath for is to resolve symlinks and most
files and directories are not symlinks.  This change skips the expensive
realpath call for non-symlinks.
@typescript-bot typescript-bot added the For Uncommitted Bug PR for untriaged, rejected, closed or missing bug label Oct 27, 2020
@amcasey
Copy link
Member Author

amcasey commented Oct 27, 2020

@typescript-bot perf test this

@typescript-bot
Copy link
Collaborator

typescript-bot commented Oct 27, 2020

Heya @amcasey, I've started to run the perf test suite on this PR at 56f9d5e. You can monitor the build here.

Update: The results are in!

@amcasey
Copy link
Member Author

amcasey commented Oct 27, 2020

I don't expect the perf test to show an improvement since the benefit to tsc seems to be negligible (the expense in tsserver seems to come primarily from ScriptInfo.ensureRealPath and some extra directoryExists checks).

@typescript-bot
Copy link
Collaborator

@amcasey
The results of the perf run you requested are in!

Here they are:

Comparison Report - master..41288

Metric master 41288 Delta Best Worst
Angular - node (v10.16.3, x64)
Memory used 350,582k (± 0.02%) 350,528k (± 0.02%) -55k (- 0.02%) 350,360k 350,783k
Parse Time 2.07s (± 0.39%) 2.07s (± 0.53%) +0.00s (+ 0.14%) 2.05s 2.09s
Bind Time 0.84s (± 0.83%) 0.84s (± 0.81%) +0.00s (+ 0.36%) 0.83s 0.86s
Check Time 4.97s (± 0.47%) 4.98s (± 0.58%) +0.01s (+ 0.14%) 4.92s 5.06s
Emit Time 5.30s (± 0.61%) 5.33s (± 0.77%) +0.03s (+ 0.51%) 5.25s 5.43s
Total Time 13.19s (± 0.32%) 13.23s (± 0.49%) +0.04s (+ 0.30%) 13.09s 13.39s
Monaco - node (v10.16.3, x64)
Memory used 354,616k (± 0.02%) 354,591k (± 0.01%) -25k (- 0.01%) 354,507k 354,708k
Parse Time 1.60s (± 0.51%) 1.60s (± 0.36%) 0.00s ( 0.00%) 1.59s 1.61s
Bind Time 0.72s (± 0.72%) 0.72s (± 0.56%) -0.00s (- 0.28%) 0.71s 0.73s
Check Time 5.13s (± 0.65%) 5.10s (± 0.47%) -0.03s (- 0.51%) 5.05s 5.15s
Emit Time 2.82s (± 0.79%) 2.80s (± 0.74%) -0.02s (- 0.64%) 2.76s 2.84s
Total Time 10.27s (± 0.43%) 10.23s (± 0.21%) -0.04s (- 0.40%) 10.19s 10.29s
TFS - node (v10.16.3, x64)
Memory used 307,880k (± 0.02%) 307,859k (± 0.02%) -22k (- 0.01%) 307,739k 307,985k
Parse Time 1.24s (± 0.54%) 1.24s (± 0.71%) 0.00s ( 0.00%) 1.22s 1.25s
Bind Time 0.68s (± 0.88%) 0.67s (± 1.32%) -0.00s (- 0.30%) 0.64s 0.68s
Check Time 4.58s (± 0.47%) 4.60s (± 0.64%) +0.01s (+ 0.24%) 4.53s 4.67s
Emit Time 2.92s (± 0.69%) 2.92s (± 0.78%) +0.00s (+ 0.10%) 2.86s 2.96s
Total Time 9.42s (± 0.35%) 9.43s (± 0.51%) +0.01s (+ 0.10%) 9.31s 9.53s
material-ui - node (v10.16.3, x64)
Memory used 489,312k (± 0.01%) 489,247k (± 0.01%) -65k (- 0.01%) 489,109k 489,390k
Parse Time 2.07s (± 0.46%) 2.07s (± 0.58%) +0.00s (+ 0.19%) 2.04s 2.09s
Bind Time 0.65s (± 0.72%) 0.65s (± 0.75%) +0.00s (+ 0.62%) 0.64s 0.66s
Check Time 13.51s (± 0.77%) 13.56s (± 0.73%) +0.06s (+ 0.43%) 13.42s 13.88s
Emit Time 0.00s (± 0.00%) 0.00s (± 0.00%) 0.00s ( NaN%) 0.00s 0.00s
Total Time 16.22s (± 0.68%) 16.29s (± 0.67%) +0.07s (+ 0.41%) 16.10s 16.63s
Angular - node (v12.1.0, x64)
Memory used 327,745k (± 0.03%) 327,921k (± 0.02%) +176k (+ 0.05%) 327,785k 328,068k
Parse Time 2.06s (± 0.87%) 2.06s (± 0.66%) +0.00s (+ 0.19%) 2.02s 2.08s
Bind Time 0.81s (± 0.69%) 0.82s (± 0.81%) +0.01s (+ 1.49%) 0.81s 0.84s
Check Time 4.90s (± 0.31%) 4.92s (± 0.54%) +0.03s (+ 0.53%) 4.88s 4.99s
Emit Time 5.48s (± 0.57%) 5.48s (± 0.52%) +0.00s (+ 0.02%) 5.43s 5.58s
Total Time 13.24s (± 0.29%) 13.29s (± 0.33%) +0.04s (+ 0.31%) 13.20s 13.37s
Monaco - node (v12.1.0, x64)
Memory used 336,763k (± 0.01%) 336,685k (± 0.04%) -79k (- 0.02%) 336,165k 336,944k
Parse Time 1.58s (± 0.81%) 1.59s (± 0.76%) +0.01s (+ 0.38%) 1.56s 1.61s
Bind Time 0.70s (± 0.74%) 0.71s (± 1.17%) +0.01s (+ 1.00%) 0.69s 0.73s
Check Time 4.92s (± 0.35%) 4.94s (± 0.45%) +0.02s (+ 0.37%) 4.90s 5.00s
Emit Time 2.87s (± 0.93%) 2.87s (± 0.87%) +0.00s (+ 0.00%) 2.83s 2.95s
Total Time 10.07s (± 0.34%) 10.10s (± 0.39%) +0.03s (+ 0.30%) 10.04s 10.21s
TFS - node (v12.1.0, x64)
Memory used 292,055k (± 0.02%) 292,124k (± 0.05%) +68k (+ 0.02%) 291,907k 292,575k
Parse Time 1.25s (± 0.56%) 1.25s (± 0.85%) +0.00s (+ 0.24%) 1.23s 1.28s
Bind Time 0.65s (± 1.03%) 0.65s (± 0.58%) -0.00s (- 0.31%) 0.64s 0.65s
Check Time 4.51s (± 0.59%) 4.51s (± 0.67%) -0.00s (- 0.04%) 4.46s 4.59s
Emit Time 2.95s (± 0.57%) 2.96s (± 0.64%) +0.02s (+ 0.54%) 2.92s 3.01s
Total Time 9.35s (± 0.34%) 9.37s (± 0.49%) +0.01s (+ 0.16%) 9.29s 9.48s
material-ui - node (v12.1.0, x64)
Memory used 467,316k (± 0.01%) 467,250k (± 0.06%) -67k (- 0.01%) 466,144k 467,539k
Parse Time 2.09s (± 0.42%) 2.08s (± 0.51%) -0.00s (- 0.19%) 2.06s 2.11s
Bind Time 0.64s (± 0.69%) 0.65s (± 1.05%) +0.00s (+ 0.62%) 0.64s 0.67s
Check Time 11.99s (± 0.48%) 12.09s (± 0.77%) +0.10s (+ 0.83%) 11.89s 12.25s
Emit Time 0.00s (± 0.00%) 0.00s (± 0.00%) 0.00s ( NaN%) 0.00s 0.00s
Total Time 14.72s (± 0.39%) 14.82s (± 0.62%) +0.10s (+ 0.66%) 14.62s 14.98s
Angular - node (v8.9.0, x64)
Memory used 353,022k (± 0.02%) 352,950k (± 0.02%) -72k (- 0.02%) 352,780k 353,116k
Parse Time 2.65s (± 0.38%) 2.63s (± 0.29%) -0.02s (- 0.64%) 2.61s 2.64s
Bind Time 0.88s (± 0.80%) 0.89s (± 0.58%) +0.01s (+ 1.14%) 0.88s 0.90s
Check Time 5.60s (± 0.51%) 5.58s (± 0.53%) -0.02s (- 0.39%) 5.52s 5.63s
Emit Time 6.36s (± 0.79%) 6.25s (± 1.27%) -0.11s (- 1.71%) 6.13s 6.50s
Total Time 15.49s (± 0.46%) 15.35s (± 0.61%) -0.14s (- 0.90%) 15.16s 15.58s
Monaco - node (v8.9.0, x64)
Memory used 358,439k (± 0.02%) 358,452k (± 0.01%) +13k (+ 0.00%) 358,351k 358,576k
Parse Time 1.93s (± 0.29%) 1.93s (± 0.40%) +0.00s (+ 0.05%) 1.91s 1.95s
Bind Time 0.90s (± 1.15%) 0.91s (± 0.82%) +0.00s (+ 0.55%) 0.89s 0.92s
Check Time 5.66s (± 0.73%) 5.65s (± 0.45%) -0.01s (- 0.26%) 5.60s 5.72s
Emit Time 3.36s (± 1.46%) 3.37s (± 1.16%) +0.01s (+ 0.27%) 3.27s 3.43s
Total Time 11.85s (± 0.68%) 11.85s (± 0.40%) -0.01s (- 0.04%) 11.70s 11.96s
TFS - node (v8.9.0, x64)
Memory used 310,265k (± 0.02%) 310,319k (± 0.02%) +54k (+ 0.02%) 310,232k 310,533k
Parse Time 1.57s (± 0.49%) 1.57s (± 0.46%) -0.00s (- 0.19%) 1.56s 1.59s
Bind Time 0.68s (± 0.54%) 0.68s (± 0.70%) -0.00s (- 0.29%) 0.67s 0.69s
Check Time 5.35s (± 0.49%) 5.32s (± 0.50%) -0.03s (- 0.65%) 5.27s 5.40s
Emit Time 2.98s (± 0.53%) 2.98s (± 0.54%) -0.00s (- 0.03%) 2.93s 3.00s
Total Time 10.59s (± 0.34%) 10.54s (± 0.35%) -0.04s (- 0.43%) 10.49s 10.67s
material-ui - node (v8.9.0, x64)
Memory used 496,221k (± 0.02%) 496,156k (± 0.01%) -66k (- 0.01%) 496,085k 496,279k
Parse Time 2.49s (± 0.52%) 2.48s (± 0.67%) -0.01s (- 0.36%) 2.44s 2.52s
Bind Time 0.82s (± 0.99%) 0.83s (± 1.05%) +0.01s (+ 0.98%) 0.81s 0.85s
Check Time 17.99s (± 1.03%) 17.86s (± 1.01%) -0.13s (- 0.73%) 17.44s 18.22s
Emit Time 0.00s (± 0.00%) 0.00s (± 0.00%) 0.00s ( NaN%) 0.00s 0.00s
Total Time 21.31s (± 0.91%) 21.18s (± 0.89%) -0.13s (- 0.62%) 20.74s 21.54s
Angular - node (v8.9.0, x86)
Memory used 202,046k (± 0.01%) 202,050k (± 0.02%) +4k (+ 0.00%) 201,929k 202,138k
Parse Time 2.54s (± 0.50%) 2.60s (± 1.28%) +0.05s (+ 2.12%) 2.53s 2.67s
Bind Time 1.01s (± 0.59%) 1.07s (± 0.76%) +0.06s (+ 5.82%) 1.06s 1.09s
Check Time 5.08s (± 0.68%) 5.08s (± 0.52%) +0.00s (+ 0.04%) 5.02s 5.12s
Emit Time 6.12s (± 1.11%) 5.94s (± 0.71%) -0.18s (- 2.91%) 5.87s 6.06s
Total Time 14.75s (± 0.57%) 14.69s (± 0.23%) -0.06s (- 0.39%) 14.62s 14.76s
Monaco - node (v8.9.0, x86)
Memory used 202,968k (± 0.01%) 202,915k (± 0.02%) -52k (- 0.03%) 202,849k 202,992k
Parse Time 1.96s (± 0.42%) 1.97s (± 0.72%) +0.01s (+ 0.51%) 1.95s 2.02s
Bind Time 0.72s (± 0.77%) 0.71s (± 0.94%) -0.01s (- 0.70%) 0.70s 0.73s
Check Time 5.75s (± 1.42%) 5.74s (± 1.20%) -0.01s (- 0.26%) 5.47s 5.81s
Emit Time 2.77s (± 2.22%) 2.78s (± 2.67%) +0.01s (+ 0.43%) 2.72s 3.07s
Total Time 11.20s (± 0.37%) 11.20s (± 0.28%) +0.00s (+ 0.02%) 11.13s 11.27s
TFS - node (v8.9.0, x86)
Memory used 177,412k (± 0.02%) 177,384k (± 0.03%) -29k (- 0.02%) 177,246k 177,463k
Parse Time 1.61s (± 1.05%) 1.62s (± 1.27%) +0.01s (+ 0.75%) 1.58s 1.69s
Bind Time 0.65s (± 1.19%) 0.65s (± 0.99%) +0.00s (+ 0.15%) 0.64s 0.67s
Check Time 4.87s (± 0.59%) 4.84s (± 0.48%) -0.03s (- 0.58%) 4.77s 4.88s
Emit Time 2.82s (± 1.15%) 2.86s (± 1.51%) +0.04s (+ 1.35%) 2.75s 2.95s
Total Time 9.95s (± 0.54%) 9.97s (± 0.69%) +0.02s (+ 0.20%) 9.82s 10.14s
material-ui - node (v8.9.0, x86)
Memory used 279,261k (± 0.01%) 279,247k (± 0.01%) -14k (- 0.00%) 279,152k 279,298k
Parse Time 2.55s (± 0.66%) 2.55s (± 0.50%) +0.00s (+ 0.04%) 2.52s 2.58s
Bind Time 0.72s (± 4.79%) 0.71s (± 1.22%) -0.01s (- 1.79%) 0.70s 0.74s
Check Time 16.40s (± 0.70%) 16.41s (± 0.64%) +0.01s (+ 0.05%) 16.18s 16.60s
Emit Time 0.00s (± 0.00%) 0.00s (± 0.00%) 0.00s ( NaN%) 0.00s 0.00s
Total Time 19.68s (± 0.61%) 19.68s (± 0.54%) -0.00s (- 0.03%) 19.42s 19.86s
System
Machine Namets-ci-ubuntu
Platformlinux 4.4.0-166-generic
Architecturex64
Available Memory16 GB
Available Memory1 GB
CPUs4 × Intel(R) Core(TM) i7-4770 CPU @ 3.40GHz
Hosts
  • node (v10.16.3, x64)
  • node (v12.1.0, x64)
  • node (v8.9.0, x64)
  • node (v8.9.0, x86)
Scenarios
  • Angular - node (v10.16.3, x64)
  • Angular - node (v12.1.0, x64)
  • Angular - node (v8.9.0, x64)
  • Angular - node (v8.9.0, x86)
  • Monaco - node (v10.16.3, x64)
  • Monaco - node (v12.1.0, x64)
  • Monaco - node (v8.9.0, x64)
  • Monaco - node (v8.9.0, x86)
  • TFS - node (v10.16.3, x64)
  • TFS - node (v12.1.0, x64)
  • TFS - node (v8.9.0, x64)
  • TFS - node (v8.9.0, x86)
  • material-ui - node (v10.16.3, x64)
  • material-ui - node (v12.1.0, x64)
  • material-ui - node (v8.9.0, x64)
  • material-ui - node (v8.9.0, x86)
Benchmark Name Iterations
Current 41288 10
Baseline master 10

@amcasey
Copy link
Member Author

amcasey commented Oct 28, 2020

Found the catch - this will do the wrong thing for a non-symlink file in a symlinked directory.

@amcasey amcasey marked this pull request as draft October 28, 2020 00:39
@amcasey
Copy link
Member Author

amcasey commented Oct 28, 2020

To be correct, this would need to lstat recursively on the path and I don't see how that could be faster than what we have now.

@amcasey amcasey closed this Oct 28, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
For Uncommitted Bug PR for untriaged, rejected, closed or missing bug
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants